package com.czkevin.cif;

import com.czkevin.cif.enchantments.Enchantment;
import com.czkevin.cif.enchantments.EnchantmentInstance;
import com.czkevin.cif.enchantments.EnchantmentRegister;
import com.czkevin.cif.utils.RomanNumber;
import de.tr7zw.nbtapi.NBTCompound;
import de.tr7zw.nbtapi.NBTContainer;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public abstract class BaseEnchantableItem extends BaseItem implements EnchantableItem {

  public static final String NBT_KEY_ENCHANTMENTS = "Enchantments";

  @Override
  public List<EnchantmentInstance> getEnchantments(CIFItemInstance instance) {
    if(instance == null) {
      throw new IllegalArgumentException("instance is null");
    }
    if(instance.data == null || !instance.data.hasKey(NBT_KEY_ENCHANTMENTS)) {
      return Collections.emptyList();
    }
    NBTCompound dataCompound = instance.data.getCompound(NBT_KEY_ENCHANTMENTS);
    if(dataCompound == null) return Collections.emptyList();
    final List<String> keys = new ArrayList<>(dataCompound.getKeys());
    if(keys.size() <= 0) return Collections.emptyList();
    List<EnchantmentInstance> list = new ArrayList<>(keys.size());
    for(int i = 0; i < keys.size(); i++) {
      final String key = keys.get(i);
      final int level = dataCompound.getInteger(key);
      Enchantment enc = EnchantmentRegister.get(key);
      if(enc != null && level > 0) {
        list.add(new EnchantmentInstance(enc, level));
      } else {
        dataCompound.removeKey(key);
      }
    }
    return Collections.unmodifiableList(list);
  }

  @Override
  public EnchantmentInstance getEnchantment(CIFItemInstance instance, Enchantment type) {
    if(instance == null) {
      throw new IllegalArgumentException("instance is null");
    }
    if(type == null) {
      throw new IllegalArgumentException("invalid type");
    }
    if(instance.data == null || !instance.data.hasKey(NBT_KEY_ENCHANTMENTS)) {
      return null;
    }
    NBTCompound compound = instance.data.getCompound(NBT_KEY_ENCHANTMENTS);
    if(!compound.hasKey(type.key())) {
      return null;
    }
    return new EnchantmentInstance(type, compound.getInteger(type.key()));
  }

  @Override
  public void setEnchantment(CIFItemInstance instance, Enchantment type, int level) {
    if(instance == null) {
      throw new IllegalArgumentException("instance is null");
    }
    if(instance.data == null) {
      instance.data = new NBTContainer();
    }
    NBTCompound enchantmentsCompound = instance.data.addCompound(NBT_KEY_ENCHANTMENTS);
    enchantmentsCompound.setInteger(type.key(), level);
  }

  @Override
  public void removeEnchantment(CIFItemInstance instance, Enchantment type) {
    if(instance == null) {
      throw new IllegalArgumentException("instance is null");
    }
    if(type == null) {
      throw new IllegalArgumentException("type is null");
    }
    if(instance.data == null || !instance.data.hasKey(NBT_KEY_ENCHANTMENTS)) return;
    NBTCompound enchantmentsCompound = instance.data.getCompound(NBT_KEY_ENCHANTMENTS);
    if(enchantmentsCompound.hasKey(type.key())) {
      enchantmentsCompound.removeKey(type.key());
    }
    if(enchantmentsCompound.getKeys().size() <= 0) {
      instance.data.removeKey(NBT_KEY_ENCHANTMENTS); // save space
    }
    if(instance.data.getKeys().size() <= 0) {
      instance.data = null;
    }
  }

  @Override
  public final boolean isBlock() {
    return false;
  }

  public List<String> getPreLore(CIFItemInstance instance) { return null; }
  public List<String> getPostLore(CIFItemInstance instance) { return null; }

  @Override
  public final List<String> getLore(CIFItemInstance instance) {
    final List<String> preLore = getPreLore(instance);
    final List<String> postLore = getPostLore(instance);
    List<String> lore = new ArrayList<>();
    if (preLore != null && preLore.size() > 0) {
      lore.addAll(preLore);
    }
    if(instance != null) {
      List<EnchantmentInstance> enchantments = getEnchantments(instance);
      if (enchantments.size() > 0) {
        lore.add("\u00a70 ");
        for (EnchantmentInstance enc : enchantments) {
          lore.add("\u00a79" + enc.type.getDisplayName() + " " + RomanNumber.toRoman(enc.level));
          final String desc = enc.type.getDescription(enc.level);
          if (desc.length() < 20) {
            lore.add(desc);
          } else {
            String[] splited = desc.split("(?<=\\G.{20})");
            for (String s : splited) {
              lore.add("\u00a77" + s);
            }
          }
        }
      } // end of add enchantments
    }
    if(postLore != null && postLore.size() > 0) {
      lore.add("\u00a70 ");
      lore.addAll(postLore);
    }
    if(lore.size() > 0) {
      lore.add("\u00a70 ");
    }
    return lore;
  }
}
